﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once

#include "GcmpGeometryInterface.h"
#include "ILine3d.h"
#include "IPolygon.h"
#include "ICurve2d.h"
#include "ICurve3d.h"
#include "ISurface.h"
#include "ILine2d.h"

namespace gcmp
{
    class Coordinate3d;
    class IFace;
    class IPlane;
    class IBody;

    class GCMP_GEOMETRY_INTERFACE_EXPORT AlgorithmProject
    {
    public:
        /// \brief  点向直线上投影（直线视为无限长处理）
        ///
        /// \param   point           点
        /// \param   pLine3d         直线
        /// \param   dParameter      投影点在直线上的参数
        /// \param   projectedPoint  投影点
        /// \return   true:成功， false：失败
        static bool Project(const Vector3d& point, const ILine3d* pLine3d, double& dParameter, Vector3d& projectedPoint);

        /// \brief  点向平面上投影（平面视为无限大处理）
        ///
        /// \param   point           点
        /// \param   pPlane          平面
        /// \param   uvParameter     投影点在直线上的参数
        /// \param   projectedPoint  投影点
        /// \return   true:成功， false：失败
        static bool Project(const Vector3d& point, const IPlane* pPlane, Vector2d& uvParameter, Vector3d& projectedPoint);

        /// \brief  点沿某一方向向平面上投影（平面视为无限大处理）
        ///
        /// \param   point                  点
        /// \param   projectingDirection    投影方向（单位向量）
        /// \param   pPlane                 平面
        /// \param   uvParameter            投影点在平面上的参数
        /// \param   projectedPoint         投影点
        /// \return   true:成功， false：失败
        static bool Project(const Vector3d& point, const Vector3d& projectingDirection, const IPlane* pPlane, Vector2d& uvParameter, Vector3d& projectedPoint);
        
        /// \brief  三维曲线向平面上投影
        ///
        /// \param pCurve3d    三维曲线
        /// \param pPlane      平面
        /// \return 投影曲线
        static OwnerPtr<ICurve2d> Project(const ICurve3d* pCurve3d, const IPlane* pPlane);

        /// \brief  三维曲线向平面上定向投影
        ///
        /// \param pCurve3d    三维曲线
        /// \param projectingDirection    投影方向
        /// \param pPlane      平面
        /// \param bNormalize  目标二维曲线是否正则化处理，默认为true
        /// \return 投影曲线
        static OwnerPtr<ICurve2d> Project(const ICurve3d* pCurve3d, const Vector3d& projectingDirection, const IPlane* pPlane, bool bNormalize = true);

        /// \brief  三维曲线向平面上投影（返回三维曲线）
        ///
        /// \param pCurve3d    三维曲线
        /// \param pSurface    曲面
        /// \return 投影曲线(三维曲线)
        static OwnerPtr<ICurve3d> ProjectReturnCurve3d(const ICurve3d* pCurve3d, const ISurface* pSurface);

        /// \brief  沿给定投影方向将源坐标系XoY平面上的多边形投影到目标坐标系XoY平面
        ///
        /// \param coordinate3dFrom        源坐标系
        /// \param pPolygonFrom            源坐标系XoY平面上的多边形
        /// \param coordinate3dTo          目标坐标系
        /// \param projectionDirection     投影方向（单位向量）
        /// \return  目标坐标系XoY平面上的投影多边形
        static OwnerPtr<IPolygon> Project(const Coordinate3d& coordinate3dFrom, const IPolygon* pPolygonFrom,
            const Coordinate3d& coordinate3dTo, const Vector3d& projectDirection);
        
        /// \brief  体向坐标系投影
        //
        /// \param coordinate3d       坐标系
        /// \param pBody              体
        /// \return  投影多边形
        static OwnerPtr<IPolygon> Project(const Coordinate3d& coordinate3d, const IBody* pBody);

        /// \brief  拓扑面向坐标系投影
        ///
        /// \param coordinate3d      坐标系
        /// \param pFace             拓扑面
        /// \return  投影多边形
        static OwnerPtr<IPolygon> Project(const Coordinate3d& coordinate3d, const IFace* pFace);

        /// \brief  拓扑面向平面投影，IFace必须是平面且与IPlane垂直
        ///
        /// \param pPlane    平面
        /// \param pFace     面
        /// \return  三维直线
        static OwnerPtr<ILine3d> Project(const IPlane* pPlane, const IFace* pFace);

        /// \brief  将二维曲线投影到直线上
        ///
        /// \param pCurve    待投影的曲线
        /// \param pLine     投影目标直线
        /// \return  投影后的二维直线
        static OwnerPtr<ILine2d> ProjectCurve2dToLine(const ICurve2d* pCurve, const ILine2d* pLine);

        /// \brief  沿源坐标系Z向平行投影二维曲线到目标坐标系XY平面
        /// \param[in] planeFrom    源坐标系
        /// \param[in] curveFrom    源二维曲线
        /// \param[in] planeTo      目标坐标系
        /// \param[in] vProjDir     投影方向
        /// \return    目标二维曲线
        static OwnerPtr<ICurve2d>  Project(const Coordinate3d& planeFrom, const ICurve2d* curveFrom, const Coordinate3d& planeTo, const Vector3d& vProjDir);
        
        /// \brief  线框体投影
        /// \param[in] wireBody         线框体
        /// \param[in] targetBody       目标体，类型为Solid
        /// \param[in] projDir          投影方向
        /// \param[in] supportFaces     指定的投影面集合，投影面须存在于目标体上。若设置为null，则默认为目标体上的所有面。
        /// \param[in] projectBodies    投影后的体
        /// \return    是否投影成功
        static bool Project(const IBody* wireBody, const IBody* targetBody, const Vector3d& projDir, const std::vector<IFace*>& supportFaces, std::vector<OwnerPtr<IBody>>& projectBodies);

    };
}
